package com.aizuda.boot.modules.business.feishu;

import com.aizuda.boot.modules.business.contract.dto.SingleResponse;
import com.aizuda.boot.modules.common.constant.enums.ResponseCodeEnum;
import com.aizuda.boot.modules.business.contract.entity.ContractEntity;
import com.aizuda.boot.modules.business.contract.service.ContractService;
import com.aizuda.boot.modules.flw.service.IFlwProcessService;
import com.aizuda.bpm.engine.entity.FlwProcess;
import com.aizuda.bpm.engine.entity.FlwInstance;
import com.aizuda.bpm.engine.entity.FlwTaskActor;
import com.aizuda.bpm.engine.entity.FlwTask;
import com.aizuda.bpm.engine.entity.FlwHisTask;
import com.aizuda.bpm.engine.entity.FlwHisTaskActor;
import com.aizuda.bpm.engine.model.NodeAssignee;
import com.aizuda.boot.modules.system.entity.SysUser;
import com.aizuda.bpm.engine.dao.FlwHisTaskDao;
import com.aizuda.bpm.engine.dao.FlwHisTaskActorDao;
import com.aizuda.bpm.engine.FlowLongIdGenerator;
import com.aizuda.bpm.engine.core.enums.TaskState;
import com.aizuda.bpm.engine.core.enums.TaskType;
import com.aizuda.bpm.engine.core.Execution;
import com.aizuda.bpm.engine.core.FlowCreator;
import com.aizuda.bpm.engine.FlowLongEngine;
import com.aizuda.bpm.engine.model.ProcessModel;
import com.aizuda.bpm.engine.model.ModelHelper;
import com.aizuda.bpm.engine.model.NodeModel;
import com.aizuda.bpm.engine.core.enums.NodeSetType;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONArray;
import com.aizuda.boot.modules.common.MessageEvent;
import com.aizuda.boot.modules.system.service.ISysUserService;
import com.aizuda.boot.modules.business.feishu.domain.AtUsersDTO;
import com.aizuda.boot.modules.business.feishu.domain.QueryUserDTO;
import com.aizuda.boot.modules.business.feishu.domain.UserVo;
import com.aizuda.service.web.UserSession;
import com.aizuda.boot.modules.business.negotiation.mapper.ContractNegotiationInstanceMapper;
import com.aizuda.boot.modules.business.negotiation.mapper.ContractNegotiationParticipantMapper;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationInstanceEntity;
import com.aizuda.boot.modules.business.negotiation.entity.ContractNegotiationParticipantEntity;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldValueMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.*;
import org.apache.commons.collections.CollectionUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

import java.util.*;
import java.util.stream.Collectors;
import java.util.Date;
import lombok.Data;

/**
 * @Author sangyirong
 * @ClassName FeiShuBotController
 * @Version 1.0
 * @Date 2025/7/14 10:40
 */
@RestController
@RequestMapping("/feishu/bot")
@Slf4j
@Tag(name = "消息推送接口")
public class FeiShuBotController {

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Resource
    private ContractService contractService;
    
    @Resource
    private IFlwProcessService flwProcessService;
    
    @Resource
    private FlowLongEngine flowLongEngine;
    
    @Resource
    private ContractNegotiationInstanceMapper contractNegotiationInstanceMapper;
    
    @Resource
    private ContractNegotiationParticipantMapper contractNegotiationParticipantMapper;
    
    @Resource
    private ContractFieldValueMapper contractFieldValueMapper;
    
    @Resource
    private FlwHisTaskDao hisTaskDao;
    
    @Resource
    private FlwHisTaskActorDao hisTaskActorDao;
    
    @Resource
    private FlowLongIdGenerator flowLongIdGenerator;

    @Operation(summary = "获取可at的用户列表")
    @PostMapping("/getAtUsers")
    public SingleResponse<List<UserVo>> getAtUsers(@RequestBody QueryUserDTO queryUserDTO) {
        return sysUserService.getAtUsers(queryUserDTO);
    }

    @Operation(summary = "at用户发送消息")
    @PostMapping("/atUsers")
    public SingleResponse<Boolean> atUsers(@RequestBody AtUsersDTO atUsersDTO){
        try {
            UserSession loginInfo = UserSession.getLoginInfo();
            
            // 发送消息事件
            MessageEvent messageEvent = new MessageEvent();
            messageEvent.setTitle(atUsersDTO.getTitle());
            messageEvent.setContent(atUsersDTO.getContent());
            messageEvent.setBusinessType(atUsersDTO.getBusinessType());
            messageEvent.setUserIds(atUsersDTO.getUserIds());
            messageEvent.setCreateId(loginInfo.getId());
            messageEvent.setCreateBy(loginInfo.getUsername());
            messageEvent.setCategory(1);
            messageEvent.setUrl(atUsersDTO.getUrl());
            applicationEventPublisher.publishEvent(messageEvent);
            
            // 创建抄送任务（如果提供了instanceId）
            if (atUsersDTO.getInstanceId() != null) {
                createCopyTask(atUsersDTO, loginInfo);
            }
            
            return SingleResponse.success();
        }catch (Exception e){
            log.error("飞书@用户发送消息异常", e);
            return SingleResponse.failure(ResponseCodeEnum.DEFAULT_EXCEPTION.getCode(), ResponseCodeEnum.DEFAULT_EXCEPTION.getMsg());
        }
    }

    /**
     * 创建抄送任务
     * @param atUsersDTO 用户信息
     * @param loginInfo 登录用户信息
     */
    private void createCopyTask(AtUsersDTO atUsersDTO, UserSession loginInfo) {
        try {
            // 1. 直接构造历史任务对象
            FlwHisTask hisTask = new FlwHisTask();
            hisTask.setId(flowLongIdGenerator.getId(hisTask.getId()));
            hisTask.setInstanceId(atUsersDTO.getInstanceId());
            hisTask.setCreateId(loginInfo.getUserId().toString());
            hisTask.setCreateBy(loginInfo.getUsername());
            hisTask.setCreateTime(new Date());
            hisTask.setTaskName("抄送任务");
            hisTask.setTaskKey("copy_task");
            hisTask.setTaskType(TaskType.cc.getValue());
            hisTask.setTaskState(TaskState.complete.getValue());
            hisTask.setFinishTime(new Date());
            hisTask.calculateDuration();
            
            // 2. 插入历史任务
            if (!hisTaskDao.insert(hisTask)) {
                log.error("插入历史任务失败，实例ID: {}", atUsersDTO.getInstanceId());
                return;
            }
            
            // 3. 为每个用户创建历史任务参与者记录
            for (Long userId : atUsersDTO.getUserIds()) {
                // 查询用户信息获取用户名
                SysUser user = sysUserService.getById(userId);
                
                FlwHisTaskActor hisTaskActor = new FlwHisTaskActor();
                hisTaskActor.setId(flowLongIdGenerator.getId(hisTaskActor.getId()));
                hisTaskActor.setInstanceId(atUsersDTO.getInstanceId());
                hisTaskActor.setTaskId(hisTask.getId());
                hisTaskActor.setActorId(userId.toString());
                hisTaskActor.setActorName(user != null ? user.getUsername() : "未知用户");
                hisTaskActor.setActorType(0); // 0表示用户类型
                hisTaskActor.setWeight(6); // 6表示抄送人
                
                if (!hisTaskActorDao.insert(hisTaskActor)) {
                    log.error("插入历史任务参与者失败，用户ID: {}, 任务ID: {}", userId, hisTask.getId());
                }
            }
            
            log.info("成功创建抄送任务，实例ID: {}, 任务ID: {}, 抄送用户数: {}", 
                    atUsersDTO.getInstanceId(), hisTask.getId(), atUsersDTO.getUserIds().size());
        } catch (Exception e) {
            log.error("创建抄送任务异常，实例ID: {}", atUsersDTO.getInstanceId(), e);
        }
    }

    @Operation(summary = "查询审批和协商中的人员")
    @PostMapping("/getProcessParticipants")
    public SingleResponse<List<UserVo>> getProcessParticipantsEnhanced(
            @RequestBody @Parameter(description = "查询参数") ProcessParticipantsDTO dto) {
        try {
            log.info("查询审批和协商中的人员（增强版），合同ID: {}, 查询类型: {}", 
                    dto.getContractId(), dto.getQueryType());
            
            // 1. 查询合同信息
            ContractEntity contract = contractService.getById(dto.getContractId());
            if (contract == null) {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "合同不存在");
            }
            
            Long processId = null;
            String processType = "";
            
            // 2. 根据查询类型获取参与用户
            List<UserVo> users;
            if (dto.getQueryType() == 0) {
                // 协商流程：直接查询协商参与者
                users = getProcessParticipantsForNegotiation(dto.getContractId());
                log.info("查询到协商流程参与用户数量: {}", users.size());
            } else if (dto.getQueryType() == 1) {
                // 审批流程：使用原有的复杂逻辑
                processId = contract.getApprovalProcessId();
                processType = "审批";
                
                if (processId == null) {
                    log.info("合同 {} 的{}流程ID为空", dto.getContractId(), processType);
                    return SingleResponse.of(new ArrayList<>());
                }
                
                log.info("查询{}流程，流程ID: {}", processType, processId);
                
                // 3. 查询流程定义
                FlwProcess flwProcess = flwProcessService.getById(processId);
                if (flwProcess == null) {
                    return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "流程定义不存在");
                }
                
                String modelContent = flwProcess.getModelContent();
                if (modelContent == null || modelContent.trim().isEmpty()) {
                    log.info("流程 {} 的model_content为空", processId);
                    return SingleResponse.of(new ArrayList<>());
                }
                
                // 4. 获取发起人用户ID（从contract_field_value表中获取apply_people字段值）
                Long initiatorUserId = getInitiatorUserIdFromContract(dto.getContractId());
                
                // 5. 获取表单参数（从contract表的content字段中解析）
                Map<String, Object> formArgs = getFormArgsFromContract(contract);
                
                // 6. 动态解析所有审批人
                Set<Long> allUserIds = extractAllParticipantsEnhanced(flwProcess, initiatorUserId, formArgs);
                log.info("从{}流程中动态解析出用户ID数量: {}", processType, allUserIds.size());
                
                if (allUserIds.isEmpty()) {
                    return SingleResponse.of(new ArrayList<>());
                }
                
                // 7. 根据用户ID查询用户信息
                users = getUsersByIds(new ArrayList<>(allUserIds));
                log.info("查询到{}流程参与用户数量: {}", processType, users.size());
            } else {
                return SingleResponse.failure(ResponseCodeEnum.SHOW_MSG.getCode(), "无效的查询类型");
            }
            
            return SingleResponse.of(users);
            
        } catch (Exception e) {
            log.error("查询审批和协商中的人员失败（增强版）", e);
            return SingleResponse.failure(ResponseCodeEnum.DEFAULT_EXCEPTION.getCode(), "查询失败: " + e.getMessage());
        }
    }
    
    /**
     * 从contract_field_value表中获取发起人用户ID
     */
    private Long getInitiatorUserIdFromContract(Integer contractId) {
        try {
            log.debug("查询合同 {} 的发起人用户ID", contractId);
            
            // 查询contract_field_value表中apply_people字段的值
            String fieldValue = contractFieldValueMapper.getFieldValueByCode(contractId, "apply_people");
            
            if (fieldValue != null && !fieldValue.trim().isEmpty()) {
                try {
                    // apply_people字段可能包含JSON格式的用户信息，需要解析出用户ID
                    // 尝试解析JSON格式的字段值
                    JSONObject applyPeopleJson = JSON.parseObject(fieldValue);
                    if (applyPeopleJson != null && applyPeopleJson.containsKey("id")) {
                        Object idObj = applyPeopleJson.get("id");
                        if (idObj != null) {
                            Long userId = Long.valueOf(idObj.toString());
                            log.debug("从apply_people字段解析到发起人用户ID: {}", userId);
                            return userId;
                        }
                    }
                    
                    // 如果不是JSON格式，尝试直接解析为用户ID
                    Long userId = Long.valueOf(fieldValue);
                    log.debug("从apply_people字段获取到发起人用户ID: {}", userId);
                    return userId;
                    
                } catch (Exception parseException) {
                    log.warn("解析apply_people字段值失败: {}, 字段值: {}", parseException.getMessage(), fieldValue);
                }
            } else {
                log.debug("合同 {} 的apply_people字段值为空", contractId);
            }
            
            // 如果无法从apply_people字段获取发起人，回退到当前登录用户
            UserSession userSession = UserSession.getLoginInfo();
            if (userSession != null) {
                log.debug("回退使用当前登录用户ID: {}", userSession.getId());
                return userSession.getId();
            }
            
            return null;
        } catch (Exception e) {
            log.warn("获取合同 {} 的发起人用户ID失败: {}", contractId, e.getMessage());
            // 异常情况下回退到当前登录用户
            UserSession userSession = UserSession.getLoginInfo();
            return userSession != null ? userSession.getId() : null;
        }
    }
    
    /**
     * 从contract表的content字段中解析表单参数
     */
    private Map<String, Object> getFormArgsFromContract(ContractEntity contract) {
        try {
            String content = contract.getContent();
            if (content == null || content.trim().isEmpty()) {
                log.debug("合同 {} 的content字段为空", contract.getId());
                return new HashMap<>();
            }
            
            // 解析JSON内容
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(content);
            
            Map<String, Object> formArgs = new HashMap<>();
            
            // 提取formData部分
            JsonNode formDataNode = rootNode.get("formData");
            if (formDataNode != null && formDataNode.isObject()) {
                Iterator<Map.Entry<String, JsonNode>> fields = formDataNode.fields();
                while (fields.hasNext()) {
                    Map.Entry<String, JsonNode> field = fields.next();
                    String key = field.getKey();
                    JsonNode valueNode = field.getValue();
                    
                    // 根据节点类型转换值
                    Object value = convertJsonNodeToObject(valueNode);
                    formArgs.put(key, value);
                }
            }
            
            log.debug("从合同 {} 解析出表单参数数量: {}", contract.getId(), formArgs.size());
            return formArgs;
            
        } catch (Exception e) {
            log.warn("解析合同 {} 的表单参数失败: {}", contract.getId(), e.getMessage());
            return new HashMap<>();
        }
    }
    
    /**
     * 将JsonNode转换为Java对象
     */
    private Object convertJsonNodeToObject(JsonNode node) {
        if (node.isNull()) {
            return null;
        } else if (node.isBoolean()) {
            return node.booleanValue();
        } else if (node.isInt()) {
            return node.intValue();
        } else if (node.isLong()) {
            return node.longValue();
        } else if (node.isDouble()) {
            return node.doubleValue();
        } else if (node.isArray()) {
            List<Object> list = new ArrayList<>();
            for (JsonNode item : node) {
                list.add(convertJsonNodeToObject(item));
            }
            return list;
        } else if (node.isObject()) {
            Map<String, Object> map = new HashMap<>();
            Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> field = fields.next();
                map.put(field.getKey(), convertJsonNodeToObject(field.getValue()));
            }
            return map;
        } else {
            return node.textValue();
        }
    }
    
    /**
     * 动态解析流程中的所有参与者（包括主管等动态审批人）
     */
    private Set<Long> extractAllParticipantsEnhanced(FlwProcess flwProcess, Long initiatorUserId, Map<String, Object> formArgs) {
        Set<Long> allUserIds = new HashSet<>();
        
        try {
            // 1. 构建流程模型
            ProcessModel processModel = ModelHelper.buildProcessModel(flwProcess.getModelContent());
            
            // 2. 创建流程创建者
            FlowCreator flowCreator;
            if (initiatorUserId != null) {
                flowCreator = new FlowCreator(String.valueOf(initiatorUserId), "发起人");
            } else {
                // 使用当前登录用户作为默认发起人
                UserSession userSession = UserSession.getLoginInfo();
                if (userSession != null) {
                    flowCreator = new FlowCreator(String.valueOf(userSession.getId()), userSession.getUsername());
                } else {
                    flowCreator = new FlowCreator("1", "系统");
                }
            }
            
            // 3. 创建虚拟流程实例（用于执行上下文）
            FlwInstance virtualInstance = new FlwInstance();
            virtualInstance.setId(0L);
            virtualInstance.setProcessId(flwProcess.getId());
            virtualInstance.setCreateId(flowCreator.getCreateId());
            virtualInstance.setCreateBy(flowCreator.getCreateBy());
            
            // 4. 创建执行上下文
            Map<String, Object> args = formArgs != null ? new HashMap<>(formArgs) : new HashMap<>();
            Execution execution = new Execution(flowLongEngine, processModel, flowCreator, virtualInstance, args);
            
            // 5. 遍历所有节点，动态解析审批人
            List<NodeModel> allNodes = ModelHelper.getRootNodeAllChildNodes(processModel.getNodeConfig());
            for (NodeModel nodeModel : allNodes) {
                try {
                    // 先提取静态配置的用户ID
                    extractStaticUserIds(nodeModel, allUserIds);
                    
                    // 动态解析审批人（主管、角色、部门等）
                    List<FlwTaskActor> taskActors = execution.getProviderTaskActors(nodeModel);
                    if (CollectionUtils.isNotEmpty(taskActors)) {
                        for (FlwTaskActor taskActor : taskActors) {
                            if (taskActor.getActorType() == 0) { // 用户类型
                                try {
                                    Long userId = Long.valueOf(taskActor.getActorId());
                                    allUserIds.add(userId);
                                    log.debug("动态解析到审批人: {} ({}), 节点: {}", 
                                            taskActor.getActorName(), userId, nodeModel.getNodeName());
                                } catch (NumberFormatException e) {
                                    log.warn("无法解析用户ID: {}, 节点: {}", taskActor.getActorId(), nodeModel.getNodeName());
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    log.warn("解析节点 {} 的审批人失败: {}", nodeModel.getNodeName(), e.getMessage());
                }
            }
            
        } catch (Exception e) {
            log.error("动态解析流程参与者失败，回退到静态解析", e);
            // 回退到静态解析
            return extractUserIdsFromModelContent(flwProcess.getModelContent());
        }
        
        return allUserIds;
    }
    
    /**
     * 提取节点中静态配置的用户ID
     */
    private void extractStaticUserIds(NodeModel nodeModel, Set<Long> userIds) {
        if (nodeModel.getNodeAssigneeList() != null) {
            for (var assignee : nodeModel.getNodeAssigneeList()) {
                try {
                    Long userId = Long.valueOf(assignee.getId());
                    userIds.add(userId);
                } catch (NumberFormatException e) {
                    log.debug("跳过非数字用户ID: {}", assignee.getId());
                }
            }
        }
    }
    
    /**
     * 从model_content JSON中递归提取所有用户ID
     */
    private Set<Long> extractUserIdsFromModelContent(String modelContent) {
        Set<Long> userIds = new HashSet<>();
        
        try {
            JSONObject jsonObject = JSON.parseObject(modelContent);
            extractUserIdsRecursively(jsonObject, userIds);
        } catch (Exception e) {
            log.error("解析model_content JSON失败", e);
        }
        
        return userIds;
    }
    
    /**
     * 递归遍历JSON对象提取用户ID
     */
    private void extractUserIdsRecursively(Object obj, Set<Long> userIds) {
        if (obj == null) {
            return;
        }
        
        if (obj instanceof JSONObject) {
            JSONObject jsonObj = (JSONObject) obj;
            
            // 检查是否包含nodeAssigneeList
            if (jsonObj.containsKey("nodeAssigneeList")) {
                Object assigneeList = jsonObj.get("nodeAssigneeList");
                if (assigneeList instanceof JSONArray) {
                    JSONArray assigneeArray = (JSONArray) assigneeList;
                    for (int i = 0; i < assigneeArray.size(); i++) {
                        Object assignee = assigneeArray.get(i);
                        if (assignee instanceof JSONObject) {
                            JSONObject assigneeObj = (JSONObject) assignee;
                            Object idObj = assigneeObj.get("id");
                            if (idObj != null) {
                                try {
                                    Long userId = Long.valueOf(idObj.toString());
                                    userIds.add(userId);
                                    log.debug("提取到用户ID: {}, 姓名: {}", userId, assigneeObj.get("name"));
                                } catch (NumberFormatException e) {
                                    log.warn("用户ID格式错误: {}", idObj);
                                }
                            }
                        }
                    }
                }
            }
            
            // 递归遍历所有子节点
            for (String key : jsonObj.keySet()) {
                extractUserIdsRecursively(jsonObj.get(key), userIds);
            }
            
        } else if (obj instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) obj;
            for (int i = 0; i < jsonArray.size(); i++) {
                extractUserIdsRecursively(jsonArray.get(i), userIds);
            }
        }
    }
    
    /**
     * 查询协商流程参与者（简化版本）
     * 直接通过contractId查询contract_negotiation_instance，再查询参与者
     */
    private List<UserVo> getProcessParticipantsForNegotiation(Integer contractId) {
        try {
            log.info("开始查询合同ID: {} 的协商参与者", contractId);
            
            // 1. 根据contractId查询协商实例
            List<ContractNegotiationInstanceEntity> instances = contractNegotiationInstanceMapper.selectList(
                    new LambdaQueryWrapper<ContractNegotiationInstanceEntity>()
                            .eq(ContractNegotiationInstanceEntity::getContractId, contractId)
            );
            
            if (instances.isEmpty()) {
                log.info("未找到合同ID: {} 对应的协商实例", contractId);
                return new ArrayList<>();
            }
            
            // 2. 提取所有instanceId
            List<Integer> instanceIds = instances.stream()
                    .map(ContractNegotiationInstanceEntity::getId)
                    .collect(Collectors.toList());
            
            // 3. 根据instanceId查询所有参与人员
            List<ContractNegotiationParticipantEntity> participants = contractNegotiationParticipantMapper.selectList(
                    new LambdaQueryWrapper<ContractNegotiationParticipantEntity>()
                            .in(ContractNegotiationParticipantEntity::getInstanceId, instanceIds)
            );
            
            if (participants.isEmpty()) {
                log.info("未找到协商实例对应的参与者");
                return new ArrayList<>();
            }
            
            // 4. 提取所有用户ID并去重
            List<Long> userIds = participants.stream()
                    .map(ContractNegotiationParticipantEntity::getEmployeeId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
            
            log.info("查询到协商参与者用户ID数量: {}", userIds.size());
            
            // 5. 根据用户ID查询用户信息
            return getUsersByIds(userIds);
            
        } catch (Exception e) {
            log.error("查询协商流程参与者失败，合同ID: {}", contractId, e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 根据用户ID列表查询用户信息
     */
    private List<UserVo> getUsersByIds(List<Long> userIds) {
        List<UserVo> users = new ArrayList<>();
        
        try {
            QueryUserDTO queryUserDTO = new QueryUserDTO();
            queryUserDTO.setKeyword(""); // 空关键词获取所有用户
            
            SingleResponse<List<UserVo>> response = sysUserService.getAtUsers(queryUserDTO);
            if (response.isSuccess() && response.getData() != null) {
                List<UserVo> allUsers = response.getData();
                
                // 过滤出指定ID的用户
                users = allUsers.stream()
                        .filter(user -> userIds.contains(user.getUserId()))
                        .collect(Collectors.toList());
            }
        } catch (Exception e) {
            log.error("根据用户ID查询用户信息失败", e);
        }
        
        return users;
    }
    
    /**
     * 查询参数DTO
     */
    @Data
    public static class ProcessParticipantsDTO {
        @Schema(description = "合同ID", required = true)
        private Integer contractId;
        
        @Schema(description = "查询类型：0-审核，1-审批", required = true)
        private Integer queryType;
    }
}
